package com.fy.fyspace.service.impl;

import com.fy.fyspace.common.result.R;
import com.fy.fyspace.model.vo.monitor.PerformanceRecordVO;
import com.fy.fyspace.service.PerformanceMonitorService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.Statement;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

import static com.fy.fyspace.common.result.R.no;
import static com.fy.fyspace.common.result.R.ok;

/**
 * 性能监控服务实现类
 */
@Slf4j
@Service
public class PerformanceMonitorServiceImpl implements PerformanceMonitorService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private DataSource dataSource;

    // 内存存储性能记录（实际项目中可以替换为数据库存储）
    private final Map<String, PerformanceRecordVO> performanceRecords = new ConcurrentHashMap<>();
    
    // 性能统计计数器
    private final AtomicLong totalRequests = new AtomicLong(0);
    private final AtomicLong totalSlowQueries = new AtomicLong(0);
    private final AtomicLong totalExceptions = new AtomicLong(0);
    private final AtomicLong totalExecutionTime = new AtomicLong(0);

    // 监控配置
    private final Map<String, Object> monitorConfig = new HashMap<>();

    @Override
    public void savePerformanceRecord(PerformanceRecordVO record) {
        try {
            // 设置创建时间
            record.setCreateTime(LocalDateTime.now());
            
            // 保存到内存（实际项目中应该保存到数据库）
            performanceRecords.put(record.getRecordId(), record);
            
            // 更新统计信息
            totalRequests.incrementAndGet();
            totalExecutionTime.addAndGet(record.getExecutionTime());
            
            if (record.getSlowQuery()) {
                totalSlowQueries.incrementAndGet();
            }
            
            if (record.getHasException()) {
                totalExceptions.incrementAndGet();
            }
            
            // 保存到Redis（用于分布式环境）
            String redisKey = "performance:record:" + record.getRecordId();
            redisTemplate.opsForValue().set(redisKey, record);
            
            // 设置过期时间（7天）
            redisTemplate.expire(redisKey, 7 * 24 * 60 * 60, java.util.concurrent.TimeUnit.SECONDS);
            
            log.debug("性能记录已保存: {}", record.getRecordId());
            
        } catch (Exception e) {
            log.error("保存性能记录失败", e);
        }
    }

    @Override
    public R getPerformanceRecords(String monitorName, String methodName, 
                                       LocalDateTime startTime, LocalDateTime endTime, 
                                       Integer pageNo, Integer pageSize) {
        try {
            List<PerformanceRecordVO> records = performanceRecords.values().stream()
                    .filter(record -> {
                        if (monitorName != null && !monitorName.isEmpty()) {
                            if (!record.getMonitorName().contains(monitorName)) {
                                return false;
                            }
                        }
                        if (methodName != null && !methodName.isEmpty()) {
                            if (!record.getMethodName().contains(methodName)) {
                                return false;
                            }
                        }
                        if (startTime != null && record.getStartTime().isBefore(startTime)) {
                            return false;
                        }
                        if (endTime != null && record.getStartTime().isAfter(endTime)) {
                            return false;
                        }
                        return true;
                    })
                    .sorted(Comparator.comparing(PerformanceRecordVO::getStartTime).reversed())
                    .collect(Collectors.toList());

            // 分页处理
            int total = records.size();
            int start = (pageNo - 1) * pageSize;
            int end = Math.min(start + pageSize, total);
            
            List<PerformanceRecordVO> pageRecords = records.subList(start, end);

            Map<String, Object> result = new HashMap<>();
            result.put("records", pageRecords);
            result.put("total", total);
            result.put("pageNo", pageNo);
            result.put("pageSize", pageSize);
            result.put("totalPages", (total + pageSize - 1) / pageSize);

            return ok(result);
            
        } catch (Exception e) {
            log.error("获取性能记录失败", e);
            return no("获取性能记录失败: " + e.getMessage());
        }
    }

    @Override
    public R getPerformanceStatistics(LocalDateTime startTime, LocalDateTime endTime) {
        try {
            List<PerformanceRecordVO> records = performanceRecords.values().stream()
                    .filter(record -> {
                        if (startTime != null && record.getStartTime().isBefore(startTime)) {
                            return false;
                        }
                        if (endTime != null && record.getStartTime().isAfter(endTime)) {
                            return false;
                        }
                        return true;
                    })
                    .collect(Collectors.toList());

            Map<String, Object> statistics = new HashMap<>();
            
            // 基本统计
            statistics.put("totalRequests", records.size());
            statistics.put("totalSlowQueries", records.stream().filter(PerformanceRecordVO::getSlowQuery).count());
            statistics.put("totalExceptions", records.stream().filter(PerformanceRecordVO::getHasException).count());
            
            // 执行时间统计
            if (!records.isEmpty()) {
                DoubleSummaryStatistics timeStats = records.stream()
                        .mapToDouble(record -> record.getExecutionTime())
                        .summaryStatistics();
                
                statistics.put("avgExecutionTime", timeStats.getAverage());
                statistics.put("minExecutionTime", timeStats.getMin());
                statistics.put("maxExecutionTime", timeStats.getMax());
                statistics.put("totalExecutionTime", timeStats.getSum());
            }
            
            // 成功率统计
            long successCount = records.stream().filter(record -> !record.getHasException()).count();
            double successRate = records.size() > 0 ? (double) successCount / records.size() * 100 : 0;
            statistics.put("successRate", successRate);
            
            // 慢查询率统计
            double slowQueryRate = records.size() > 0 ? (double) statistics.get("totalSlowQueries") / records.size() * 100 : 0;
            statistics.put("slowQueryRate", slowQueryRate);
            
            // 按方法分组统计
            Map<String, List<PerformanceRecordVO>> methodGroups = records.stream()
                    .collect(Collectors.groupingBy(PerformanceRecordVO::getMethodName));
            
            Map<String, Object> methodStats = new HashMap<>();
            methodGroups.forEach((methodName, methodRecords) -> {
                Map<String, Object> methodData = new HashMap<>();
                methodData.put("count", methodRecords.size());
                methodData.put("avgTime", methodRecords.stream().mapToLong(PerformanceRecordVO::getExecutionTime).average().orElse(0));
                methodData.put("maxTime", methodRecords.stream().mapToLong(PerformanceRecordVO::getExecutionTime).max().orElse(0));
                methodData.put("slowCount", methodRecords.stream().filter(PerformanceRecordVO::getSlowQuery).count());
                methodData.put("exceptionCount", methodRecords.stream().filter(PerformanceRecordVO::getHasException).count());
                methodStats.put(methodName, methodData);
            });
            statistics.put("methodStatistics", methodStats);

            return ok(statistics);
            
        } catch (Exception e) {
            log.error("获取性能统计失败", e);
            return no("获取性能统计失败: " + e.getMessage());
        }
    }

    @Override
    public R getSlowQueryRecords(LocalDateTime startTime, LocalDateTime endTime, 
                                     Integer pageNo, Integer pageSize) {
        try {
            List<PerformanceRecordVO> slowRecords = performanceRecords.values().stream()
                    .filter(PerformanceRecordVO::getSlowQuery)
                    .filter(record -> {
                        if (startTime != null && record.getStartTime().isBefore(startTime)) {
                            return false;
                        }
                        if (endTime != null && record.getStartTime().isAfter(endTime)) {
                            return false;
                        }
                        return true;
                    })
                    .sorted(Comparator.comparing(PerformanceRecordVO::getExecutionTime).reversed())
                    .collect(Collectors.toList());

            // 分页处理
            int total = slowRecords.size();
            int start = (pageNo - 1) * pageSize;
            int end = Math.min(start + pageSize, total);
            
            List<PerformanceRecordVO> pageRecords = slowRecords.subList(start, end);

            Map<String, Object> result = new HashMap<>();
            result.put("records", pageRecords);
            result.put("total", total);
            result.put("pageNo", pageNo);
            result.put("pageSize", pageSize);
            result.put("totalPages", (total + pageSize - 1) / pageSize);

            return ok(result);
            
        } catch (Exception e) {
            log.error("获取慢查询记录失败", e);
            return no("获取慢查询记录失败: " + e.getMessage());
        }
    }

    @Override
    public R getExceptionRecords(LocalDateTime startTime, LocalDateTime endTime, 
                                     Integer pageNo, Integer pageSize) {
        try {
            List<PerformanceRecordVO> exceptionRecords = performanceRecords.values().stream()
                    .filter(PerformanceRecordVO::getHasException)
                    .filter(record -> {
                        if (startTime != null && record.getStartTime().isBefore(startTime)) {
                            return false;
                        }
                        if (endTime != null && record.getStartTime().isAfter(endTime)) {
                            return false;
                        }
                        return true;
                    })
                    .sorted(Comparator.comparing(PerformanceRecordVO::getStartTime).reversed())
                    .collect(Collectors.toList());

            // 分页处理
            int total = exceptionRecords.size();
            int start = (pageNo - 1) * pageSize;
            int end = Math.min(start + pageSize, total);
            
            List<PerformanceRecordVO> pageRecords = exceptionRecords.subList(start, end);

            Map<String, Object> result = new HashMap<>();
            result.put("records", pageRecords);
            result.put("total", total);
            result.put("pageNo", pageNo);
            result.put("pageSize", pageSize);
            result.put("totalPages", (total + pageSize - 1) / pageSize);

            return ok(result);
            
        } catch (Exception e) {
            log.error("获取异常记录失败", e);
            return no("获取异常记录失败: " + e.getMessage());
        }
    }

    @Override
    public R getPerformanceRanking(LocalDateTime startTime, LocalDateTime endTime, Integer limit) {
        try {
            List<PerformanceRecordVO> records = performanceRecords.values().stream()
                    .filter(record -> {
                        if (startTime != null && record.getStartTime().isBefore(startTime)) {
                            return false;
                        }
                        if (endTime != null && record.getStartTime().isAfter(endTime)) {
                            return false;
                        }
                        return true;
                    })
                    .collect(Collectors.toList());

            // 按方法名分组，计算平均执行时间
            Map<String, Double> methodAvgTimes = records.stream()
                    .collect(Collectors.groupingBy(
                            PerformanceRecordVO::getMethodName,
                            Collectors.averagingLong(PerformanceRecordVO::getExecutionTime)
                    ));

            // 排序并限制数量
            List<Map.Entry<String, Double>> ranking = methodAvgTimes.entrySet().stream()
                    .sorted(Map.Entry.<String, Double>comparingByValue().reversed())
                    .limit(limit != null ? limit : 10)
                    .collect(Collectors.toList());

            List<Map<String, Object>> result = new ArrayList<>();
            for (Map.Entry<String, Double> entry : ranking) {
                Map<String, Object> item = new HashMap<>();
                item.put("methodName", entry.getKey());
                item.put("avgExecutionTime", entry.getValue());
                result.add(item);
            }

            return ok(result);
            
        } catch (Exception e) {
            log.error("获取性能排名失败", e);
            return no("获取性能排名失败: " + e.getMessage());
        }
    }

    @Override
    public R cleanExpiredRecords(Integer days) {
        try {
            LocalDateTime cutoffTime = LocalDateTime.now().minusDays(days);
            // 先统计要删除的数量
            long removedCount = performanceRecords.values().stream()
                .filter(record -> record.getCreateTime().isBefore(cutoffTime))
                .count();
            // 再执行删除
            performanceRecords.values().removeIf(record -> record.getCreateTime().isBefore(cutoffTime));
            log.info("清理过期性能记录完成，共清理 {} 条记录", removedCount);
            return ok("清理完成，共清理 " + removedCount + " 条记录");
        } catch (Exception e) {
            log.error("清理过期记录失败", e);
            return no("清理过期记录失败: " + e.getMessage());
        }
    }

    @Override
    public R getMonitorConfig() {
        try {
            Map<String, Object> config = new HashMap<>(monitorConfig);
            config.put("defaultSlowThreshold", 1000);
            config.put("defaultLogRequest", false);
            config.put("defaultLogResponse", false);
            config.put("defaultLogException", true);
            return ok(config);
        } catch (Exception e) {
            log.error("获取监控配置失败", e);
            return no("获取监控配置失败: " + e.getMessage());
        }
    }

    @Override
    public R updateMonitorConfig(Map<String, Object> config) {
        try {
            monitorConfig.clear();
            monitorConfig.putAll(config);
            log.info("监控配置已更新: {}", config);
            return ok("监控配置更新成功");
        } catch (Exception e) {
            log.error("更新监控配置失败", e);
            return no("更新监控配置失败: " + e.getMessage());
        }
    }

    @Override
    public R testInterfacePerformance(String monitorName, Integer testCount) {
        try {
            // 这里可以实现接口性能测试逻辑
            // 目前返回模拟数据
            Map<String, Object> result = new HashMap<>();
            result.put("monitorName", monitorName);
            result.put("testCount", testCount);
            result.put("avgResponseTime", Math.random() * 100 + 50);
            result.put("minResponseTime", Math.random() * 30 + 20);
            result.put("maxResponseTime", Math.random() * 200 + 150);
            result.put("successRate", Math.random() * 20 + 80);
            result.put("testTime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            
            log.info("接口性能测试完成: {}", monitorName);
            return ok(result);
            
        } catch (Exception e) {
            log.error("接口性能测试失败", e);
            return no("接口性能测试失败: " + e.getMessage());
        }
    }

    @Override
    public R getDatabaseStatistics() {
        Map<String, Object> result = new HashMap<>();
        try (Connection conn = dataSource.getConnection()) {
            DatabaseMetaData metaData = conn.getMetaData();
            String dbName = conn.getCatalog();
            Map<String, Object> databaseInfo = new LinkedHashMap<>();
            // 基本信息
            databaseInfo.put("databaseProductName", metaData.getDatabaseProductName());
            databaseInfo.put("databaseProductVersion", metaData.getDatabaseProductVersion());
            databaseInfo.put("driverName", metaData.getDriverName());
            databaseInfo.put("driverVersion", metaData.getDriverVersion());
            databaseInfo.put("url", metaData.getURL());
            databaseInfo.put("userName", metaData.getUserName());
            databaseInfo.put("dbName", dbName);
            // 连接数、Uptime、慢查询、QPS、TPS
            int threadsConnected = 0, maxUsedConnections = 0, slowQueries = 0, uptime = 0;
            long questions = 0, commit = 0, rollback = 0;
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SHOW GLOBAL STATUS WHERE variable_name IN ('Threads_connected', 'Max_used_connections', 'Uptime', 'Slow_queries', 'Questions', 'Com_commit', 'Com_rollback')")) {
                while (rs.next()) {
                    String name = rs.getString("Variable_name");
                    String value = rs.getString("Value");
                    switch (name) {
                        case "Threads_connected": threadsConnected = Integer.parseInt(value); break;
                        case "Max_used_connections": maxUsedConnections = Integer.parseInt(value); break;
                        case "Slow_queries": slowQueries = Integer.parseInt(value); break;
                        case "Uptime": uptime = Integer.parseInt(value); break;
                        case "Questions": questions = Long.parseLong(value); break;
                        case "Com_commit": commit = Long.parseLong(value); break;
                        case "Com_rollback": rollback = Long.parseLong(value); break;
                    }
                }
            }
            double qps = uptime > 0 ? (double) questions / uptime : 0;
            double tps = uptime > 0 ? (double) (commit + rollback) / uptime : 0;
            databaseInfo.put("threadsConnected", threadsConnected);
            databaseInfo.put("maxUsedConnections", maxUsedConnections);
            databaseInfo.put("slowQueries", slowQueries);
            databaseInfo.put("uptime", uptime);
            databaseInfo.put("QPS", qps);
            databaseInfo.put("TPS", tps);
            // 数据库大小
            long dbSize = 0;
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SELECT SUM(data_length+index_length) AS total_size FROM information_schema.tables WHERE table_schema='" + dbName + "' GROUP BY table_schema")) {
                if (rs.next()) dbSize = rs.getLong("total_size");
            }
            databaseInfo.put("databaseSizeBytes", dbSize);
            result.put("databaseInfo", databaseInfo);

            // 表结构
            List<Map<String, Object>> tables = new ArrayList<>();
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SHOW TABLE STATUS FROM `" + dbName + "`")) {
                while (rs.next()) {
                    Map<String, Object> table = new LinkedHashMap<>();
                    table.put("name", rs.getString("Name"));
                    table.put("engine", rs.getString("Engine"));
                    table.put("rows", rs.getLong("Rows"));
                    table.put("dataLength", rs.getLong("Data_length"));
                    table.put("indexLength", rs.getLong("Index_length"));
                    table.put("autoIncrement", rs.getString("Auto_increment"));
                    table.put("createTime", rs.getString("Create_time"));
                    table.put("updateTime", rs.getString("Update_time"));
                    table.put("collation", rs.getString("Collation"));
                    table.put("comment", rs.getString("Comment"));
                    tables.add(table);
                }
            }
            result.put("tables", tables);

            // 主键信息
            List<Map<String, Object>> primaryKeys = new ArrayList<>();
            for (Map<String, Object> table : tables) {
                String tableName = table.get("name").toString();
                try (ResultSet rs = metaData.getPrimaryKeys(dbName, null, tableName)) {
                    while (rs.next()) {
                        Map<String, Object> pk = new LinkedHashMap<>();
                        pk.put("table", tableName);
                        pk.put("columnName", rs.getString("COLUMN_NAME"));
                        pk.put("keySeq", rs.getShort("KEY_SEQ"));
                        pk.put("pkName", rs.getString("PK_NAME"));
                        primaryKeys.add(pk);
                    }
                }
            }
            result.put("primaryKeys", primaryKeys);

            // 索引信息
            List<Map<String, Object>> indexes = new ArrayList<>();
            for (Map<String, Object> table : tables) {
                String tableName = table.get("name").toString();
                try (ResultSet rs = metaData.getIndexInfo(dbName, null, tableName, false, false)) {
                    while (rs.next()) {
                        Map<String, Object> index = new LinkedHashMap<>();
                        index.put("table", tableName);
                        index.put("indexName", rs.getString("INDEX_NAME"));
                        index.put("nonUnique", rs.getBoolean("NON_UNIQUE"));
                        index.put("columnName", rs.getString("COLUMN_NAME"));
                        index.put("indexType", rs.getString("TYPE"));
                        index.put("ordinalPosition", rs.getShort("ORDINAL_POSITION"));
                        index.put("ascOrDesc", rs.getString("ASC_OR_DESC"));
                        index.put("cardinality", rs.getLong("CARDINALITY"));
                        indexes.add(index);
                    }
                }
            }
            result.put("indexes", indexes);

            // 触发器信息
            List<Map<String, Object>> triggers = new ArrayList<>();
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SELECT * FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA='" + dbName + "'")) {
                while (rs.next()) {
                    Map<String, Object> trigger = new LinkedHashMap<>();
                    trigger.put("triggerName", rs.getString("TRIGGER_NAME"));
                    trigger.put("eventManipulation", rs.getString("EVENT_MANIPULATION"));
                    trigger.put("eventObjectTable", rs.getString("EVENT_OBJECT_TABLE"));
                    trigger.put("actionStatement", rs.getString("ACTION_STATEMENT"));
                    trigger.put("actionTiming", rs.getString("ACTION_TIMING"));
                    trigger.put("created", rs.getString("CREATED"));
                    triggers.add(trigger);
                }
            }
            result.put("triggers", triggers);
            result.put("triggerCount", triggers.size());

            // 事件信息
            List<Map<String, Object>> events = new ArrayList<>();
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SELECT * FROM information_schema.EVENTS WHERE EVENT_SCHEMA='" + dbName + "'")) {
                while (rs.next()) {
                    Map<String, Object> event = new LinkedHashMap<>();
                    event.put("eventName", rs.getString("EVENT_NAME"));
                    event.put("eventType", rs.getString("EVENT_TYPE"));
                    event.put("executeAt", rs.getString("EXECUTE_AT"));
                    event.put("intervalValue", rs.getString("INTERVAL_VALUE"));
                    event.put("intervalField", rs.getString("INTERVAL_FIELD"));
                    event.put("status", rs.getString("STATUS"));
                    event.put("created", rs.getString("CREATED"));
                    events.add(event);
                }
            }
            result.put("events", events);
            result.put("eventCount", events.size());

            // 用户信息
            List<Map<String, Object>> users = new ArrayList<>();
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SELECT user, host FROM mysql.user")) {
                while (rs.next()) {
                    Map<String, Object> user = new LinkedHashMap<>();
                    user.put("user", rs.getString("user"));
                    user.put("host", rs.getString("host"));
                    users.add(user);
                }
            }
            result.put("users", users);

            // 活跃会话
            List<Map<String, Object>> processes = new ArrayList<>();
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SHOW FULL PROCESSLIST")) {
                while (rs.next()) {
                    Map<String, Object> process = new LinkedHashMap<>();
                    process.put("id", rs.getLong("Id"));
                    process.put("user", rs.getString("User"));
                    process.put("host", rs.getString("Host"));
                    process.put("db", rs.getString("db"));
                    process.put("command", rs.getString("Command"));
                    process.put("time", rs.getLong("Time"));
                    process.put("state", rs.getString("State"));
                    process.put("info", rs.getString("Info"));
                    processes.add(process);
                }
            }
            result.put("processes", processes);
            result.put("activeSessionCount", processes.size());

            // InnoDB缓冲池信息
            String innodbStatus = "";
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SHOW ENGINE INNODB STATUS")) {
                if (rs.next()) {
                    innodbStatus = rs.getString("Status");
                }
            }
            result.put("innodbStatus", innodbStatus);

            // 性能总结
            Map<String, Object> performanceSummary = new LinkedHashMap<>();
            performanceSummary.put("QPS", qps);
            performanceSummary.put("TPS", tps);
            performanceSummary.put("slowQueries", slowQueries);
            performanceSummary.put("activeSessionCount", processes.size());
            performanceSummary.put("tableCount", tables.size());
            performanceSummary.put("indexCount", indexes.size());
            performanceSummary.put("triggerCount", triggers.size());
            performanceSummary.put("eventCount", events.size());
            performanceSummary.put("databaseSizeBytes", dbSize);
            result.put("performanceSummary", performanceSummary);

        } catch (Exception e) {
            log.error("获取MySQL数据库监控统计信息失败", e);
            return no("获取MySQL数据库监控统计信息失败: " + e.getMessage());
        }
        return ok(result);
    }
} 